using Engine;
using Game;

namespace SCIENEW {
    public class MachineToolElectricElement : ElectricElement {
        public bool m_isDispenseAllowed = true;

        public double? m_lastDispenseTime;

        public SubsystemBlockEntities m_subsystemBlockEntities;

        public SubsystemPickables m_subsystemPickables;

        public Vector3 m_position;

        public MachineToolElectricElement(SubsystemElectricity subsystemElectricity, Point3 point) : base(subsystemElectricity, new List<CellFace> { new(point.X, point.Y, point.Z, 4), new(point.X, point.Y, point.Z, 5) }) {
            m_subsystemBlockEntities = SubsystemElectricity.Project.FindSubsystem<SubsystemBlockEntities>(throwOnError: true);
            m_subsystemPickables = SubsystemElectricity.Project.FindSubsystem<SubsystemPickables>(true);
            m_position = new Vector3(point) + new Vector3(0.5f);
        }

        public override bool Simulate() {
            if (CalculateHighInputsCount(5) > 0) {
                //上端输入信号，弹出物品
                if (m_isDispenseAllowed && (!m_lastDispenseTime.HasValue || SubsystemElectricity.SubsystemTime.GameTime - m_lastDispenseTime > 0.1)) {
                    m_isDispenseAllowed = false;
                    m_lastDispenseTime = SubsystemElectricity.SubsystemTime.GameTime;
                    ComponentExCraftingTable? componentExCraftingTable = m_subsystemBlockEntities.GetBlockEntity(CellFaces[0].Point.X, CellFaces[0].Point.Y, CellFaces[0].Point.Z)?.Entity.FindComponent<ComponentExCraftingTable>();
                    if (componentExCraftingTable != null) {
                        int resultValue = componentExCraftingTable.GetSlotValue(componentExCraftingTable.ResultSlotIndex);
                        int resultCount = componentExCraftingTable.RemoveSlotItems(componentExCraftingTable.ResultSlotIndex, componentExCraftingTable.GetSlotCount(componentExCraftingTable.ResultSlotIndex));
                        if (resultCount > 0)
                            m_subsystemPickables.AddPickable(
                                resultValue,
                                resultCount,
                                m_position + Vector3.UnitY * 0.7f,
                                Vector3.UnitY * 4,
                                null
                            );
                        int remainValue = componentExCraftingTable.GetSlotValue(componentExCraftingTable.RemainsSlotIndex);
                        int remainCount = componentExCraftingTable.RemoveSlotItems(componentExCraftingTable.RemainsSlotIndex, componentExCraftingTable.GetSlotCount(componentExCraftingTable.RemainsSlotIndex));
                        if (remainCount > 0)
                            m_subsystemPickables.AddPickable(
                                remainValue,
                                remainCount,
                                m_position + Vector3.UnitY * 0.7f,
                                Vector3.UnitY * 4,
                                null
                            );
                    }
                }
            }
            else {
                m_isDispenseAllowed = true;
            }

            //下方
            float inputValue = -1;
            foreach (ElectricConnection connection in this.Connections) {
                if (connection.ConnectorType != ElectricConnectorType.Output
                    && connection.NeighborConnectorType != ElectricConnectorType.Input
                    && connection.CellFace.Face == 4)
                    inputValue = MathUtils.Max(connection.NeighborElectricElement.GetOutputVoltage(connection.NeighborConnectorFace), inputValue);
            }
            ComponentExCraftingTable? componentExCraftingTable2 = m_subsystemBlockEntities.GetBlockEntity(CellFaces[0].Point.X, CellFaces[0].Point.Y, CellFaces[0].Point.Z)?.Entity.FindComponent<ComponentExCraftingTable>();
            if (componentExCraftingTable2 != null) {
                if (inputValue < 0) //如果下方foreach一趟下来还是-1，说明下方未接入端口，工作台可自由接受物品
                    componentExCraftingTable2.RequireItemSlotIndex = null;
                else {
                    int slotIndex = (int)MathF.Round(inputValue * 15f);
                    componentExCraftingTable2.RequireItemSlotIndex = slotIndex;
                }
            }
            return false;
        }

        public int CalculateHighInputsCount(int face) {
            int highInputsCount = 0;
            foreach (ElectricConnection connection in this.Connections) {
                if (connection.ConnectorType != ElectricConnectorType.Output
                    && connection.NeighborConnectorType != ElectricConnectorType.Input
                    && connection.CellFace.Face == face
                    && IsSignalHigh(connection.NeighborElectricElement.GetOutputVoltage(connection.NeighborConnectorFace)))
                    ++highInputsCount;
            }
            return highInputsCount;
        }
    }
}